package top.codedance.iotp.client.plugins.sync.system;

import com.alibaba.fastjson.JSONObject;
import top.codedance.iotp.client.ClientApplication;
import top.codedance.iotp.common.executer.SyncAbstractExecuter;
import top.codedance.iotp.common.entity.PluginResultEntity;
import com.sshtools.forker.client.ForkerBuilder;
import com.sshtools.forker.client.PowerShellBuilder;
import com.sshtools.forker.common.IO;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.log4j.Logger;

import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

public class SystemExecuterImpl extends SyncAbstractExecuter {
    private static Logger logger = ClientApplication.getLogger(SystemExecuterImpl.class);

    @Override
    public PluginResultEntity exec(byte[] data, String taskId) {
        PluginResultEntity endResult = new PluginResultEntity();
        ByteArrayOutputStream baout = new ByteArrayOutputStream();
        try {
            String cmd = new String(data, StandardCharsets.UTF_8);
            boolean isPowershell = false;
            try {
                JSONObject tmpCmd = JSONObject.parseObject(cmd);
                cmd = tmpCmd.getString("cmd");
                isPowershell = tmpCmd.getBoolean("powershell");
            } catch (Exception e) {
            }
            logger.debug("Command:  " + cmd);
            ForkerBuilder builder;
            if(isPowershell){
                builder = new PowerShellBuilder();
            }else{
                builder = new ForkerBuilder();
            }
            builder.io(IO.IO).redirectErrorStream(true);
            if (SystemUtils.IS_OS_LINUX || SystemUtils.IS_OS_MAC) {
                builder.command("sh", "-c", cmd);
                final Process p = builder.start();
                ClientApplication.syncWorkerPool.submit(() -> {
                    try {
                        IOUtils.copy(p.getInputStream(), baout);
                    }catch (Exception e){}
                });
                boolean status = p.waitFor(5, TimeUnit.SECONDS);
                if(!status){
                    throw new Exception("Please enter a non interactive command!");
                }
                p.destroyForcibly();

                endResult.setOk(true);
                endResult.setContext(new String(baout.toByteArray(), System.getProperty("sun.jnu.encoding")));
            } else if (SystemUtils.IS_OS_WINDOWS) {
                if(!isPowershell){
                    builder.command("cmd", "/c", cmd);
                }else {
                    builder.command(cmd);
                }
                final Process p = builder.start();
                ClientApplication.syncWorkerPool.submit(() -> {
                    try {
                        IOUtils.copy(p.getInputStream(), baout);
                    }catch (Exception e){}
                });
                boolean status = p.waitFor(5, TimeUnit.SECONDS);
                if(!status){
                    throw new Exception("Please enter a non interactive command!");
                }
                p.destroyForcibly();

                endResult.setOk(true);
                endResult.setContext(new String(baout.toByteArray(), System.getProperty("sun.jnu.encoding")));
            } else {
                endResult.put("ok", false);
                endResult.setMsg("Unsupported this platform.");
            }
        } catch (Exception ex) {
            logger.debug(ex.getMessage());
            endResult.setOk(false);
            endResult.setMsg(ex.getMessage());
        }
        return endResult;
    }
}
